<?php

namespace yunj\init;

use yunj\init\step\BaseDataInit;
use yunj\init\step\Step;
use yunj\init\traits\Output;

class Init {

    use Output;

    // 步骤
    const STEPS = [
        [
            'desc' => '环境检测',
            'class' => 'EnvCheck',
        ],
        [
            'desc' => '配置文件更新/初始化',
            'class' => 'ConfigInit',
        ],
        [
            'desc' => '静态文件更新/初始化',
            'class' => 'StaticInit',
        ],
        [
            'desc' => '基础数据更新/初始化',
            'class' => 'BaseDataInit',
        ],
        [
            'desc' => 'Demo数据更新/初始化',
            'class' => 'DemoDataInit',
        ],
    ];

    public function handle() {
        $this->success("初始化开始！！！", true, false);
        // 拿到要执行安装的步骤
        $stepNoArr = [];
        $allStepNoArr = range(1, count(self::STEPS));

        // 是否全部初始化
        $isAllInitialized = false;
        if (is_initialized()) {
            // 已初始化，是否重新初始化，还是执行指定步骤
            $this->warning("您已执行过初始化程序！");
            $res = $this->ask("1. 执行指定步骤\r\n2. 重新初始化\r\n其他默认退出");
            switch ($res) {
                case 1:
                    $this->showSteps();
                    $step = $this->ask("请选择要执行的步骤编号（其他默认退出）");
                    if (in_array($step, $allStepNoArr)) {
                        $stepNoArr = [$step];
                    }
                    break;
                case 2:
                    $isAllInitialized = true;
                    $this->showSteps();
                    $stepNoArr = $allStepNoArr;
                    break;
            }
        } else {
            $isAllInitialized = true;
            // 没有初始化过，显示初始化步骤
            $this->showSteps();
            $stepNoArr = $allStepNoArr;
        }
        if (!$stepNoArr) {
            $this->warning("已退出初始化", false);
            return;
        }
        // 执行步骤
        $steps = [];
        $baseDataInitInstance = null;
        foreach ($stepNoArr as $stepNo) {
            $step = self::STEPS[$stepNo - 1];
            ['desc' => $stepDesc, 'class' => $stepClass] = $step;
            $step['no'] = $stepNo;
            $this->success("{$stepNo}. {$stepDesc} 开始...", true, false);
            $stepClass = "\\yunj\\init\\step\\" . $stepClass;
            /** @var Step $stepInstance */
            $stepInstance = new $stepClass($stepDesc);
            $step['instance'] = $stepInstance;
            $steps[] = $step;

            $res = $stepInstance->handle();
            // 基础数据初始化
            if ($stepInstance instanceof BaseDataInit) {
                $baseDataInitInstance = $stepInstance;
            }
            if ($res == Step::RES_SKIP) {
                $this->skip($stepDesc);
                continue;
            }
            $this->success($stepDesc, true);
        }
        // 日志记录
        $this->logRecord($steps);
        // 安装成功提示
        $this->successTips($isAllInitialized, $steps, $baseDataInitInstance);
    }

    // 显示初始化步骤
    private function showSteps() {
        $this->success("【初始化步骤】", true, false);
        $no = 1;
        $desc = "";
        foreach (self::STEPS as $step) {
            $desc .= $no . ". " . $step['desc'] . "\r\n";
            $no++;
        }
        $this->info($desc);
    }

    // 日志记录
    private function logRecord(array $steps) {
        $filePath = ds_replace(YUNJ_PATH . '/initialized.log');
        $contentToAppend = "";
        foreach ($steps as $step) {
            ['no' => $stepNo, 'desc' => $stepDesc] = $step;
            $contentToAppend .= ($contentToAppend ? '、' : '') . "{$stepNo}. {$stepDesc}";
        }
        $contentToAppend = (file_exists($filePath) ? "\r\n\r\n" : "") . "[" . date('Y-m-d H:i:s') . "] 执行初始化成功\r\n执行步骤：" . $contentToAppend;
        // 打开文件，将文件指针移动到文件末尾
        if ($fp = @fopen($filePath, 'a')) {
            // 写入内容
            @fwrite($fp, $contentToAppend);
            // 关闭文件句柄
            @fclose($fp);
        }
    }

    /**
     * 安装成功提示
     * @param bool $isAllInitialized    是否全部初始换
     * @param array $steps
     * @param BaseDataInit|null $baseDataInitInstance
     */
    private function successTips(bool $isAllInitialized, array $steps, $baseDataInitInstance) {
        if ($isAllInitialized) {
            $this->success("初始化完成", true);
        }
        if (!$baseDataInitInstance || !$baseDataInitInstance->isInit()) {
            // 没有初始化基础数据，直接结束
            return;
        }

        $tips = "管理后台登录：";
        $loginUrl = "网站域名";
        if ($appHost = config('app.app_host')) {
            $loginUrl = $appHost;
            if (substr($loginUrl, -1) == '/') $loginUrl = substr($loginUrl, 0, -1);
        }
        $loginUrlSuffix = '/' . YUNJ_ADMIN_ENTRANCE . '/login';
        $tips .= $loginUrl . '/index.php' . $loginUrlSuffix . ' 忽略入口文件直接访问：' . $loginUrl . $loginUrlSuffix;
        $tips .= "\r\n管理员【账户】：{$baseDataInitInstance->getUsername()}\r\n管理员【密码】：{$baseDataInitInstance->getPassword()}";
        $this->info($tips, false);
    }
}
